/*
 *  /linux-3.0.8/drivers/media/video/gt2440_ov9650.h
*/
#ifndef __GT2440_OV9650_H
#define __GT2440_OV9650_H




/* help data structure */
struct gt2440_ov9650_reg{
	u8 addr;
	u8 value;
};
struct gt2440_ov9650_framesize {
	u16 	width;
	u16 	height;
	u8 	com7_reg;
};

struct gt2440_ov9650_pixelcode {
	enum v4l2_mbus_pixelcode pixelcode;
	u32 colorspace;
};



/* plat data structure */
struct gt2440_ov9650_platdata {
	unsigned long mclk_frequency;
	int gpio_pwdn;
	int gpio_reset;

	int (*init_gpio)(struct gt2440_ov9650_platdata *pdata);
	int (*exit_gpio)(struct gt2440_ov9650_platdata *pdata);
	int (*set_power)(struct gt2440_ov9650_platdata *pdata, int on);
};



/* driver data structure */
enum gpio_id {
	GPIO_PWDN,
	GPIO_RST,
	NUM_GPIOS,
};
enum v4l2_mbus_type {
	V4L2_MBUS_PARALLEL,
	V4L2_MBUS_BT656,
	V4L2_MBUS_CSI2,
};

struct gt2440_ov9650_ctrl {
	struct v4l2_ctrl_handler handler;
	struct v4l2_ctrl *brightness;
	struct v4l2_ctrl *saturation;
	struct v4l2_ctrl *contrast;
	
	struct v4l2_ctrl *auto_exp;
	struct v4l2_ctrl *exposure;
	
	struct v4l2_ctrl *auto_wb;
	struct v4l2_ctrl *hflip;
	struct v4l2_ctrl *vflip;
};
struct gt2440_ov9650_info {
	/* critical ops:  must remove all the code about media */
	//struct media_pad		pad;

	struct v4l2_subdev		v4l2_sub;
	
	struct v4l2_mbus_framefmt framefmt;
	
	struct gt2440_ov9650_ctrl ctrl;

	struct gt2440_ov9650_platdata *pdata;
	
	struct device *dev;
	
	int gpios[NUM_GPIOS];
	unsigned long mclk_frequency;
	
	unsigned short streaming;
	unsigned short power;
	u8 apply_fmt;
	u8 com7_reg;
	enum v4l2_mbus_type bus_type;
	struct mutex lock;
};





#define REG_GAIN		0x00
#define REG_BLUE		0x01
#define REG_RED			0x02
#define REG_VREF		0x03
#define REG_COM1		0x04
#define  COM1_CCIR656		0x40
#define REG_B_AVE		0x05
#define REG_GB_AVE		0x06
#define REG_GR_AVE		0x07
#define REG_R_AVE		0x08
#define REG_COM2		0x09
#define REG_PID			0x0a	/* Product ID MSB */
#define REG_VER			0x0b	/* Product ID LSB */
#define REG_COM3		0x0c
#define  COM3_SWAP		0x40
#define  COM3_VARIOPIXEL1	0x04
#define REG_COM4		0x0d	/* Vario Pixels  */
#define  COM4_VARIOPIXEL2	0x80
#define REG_COM5		0x0e	/* System clock options */
#define  COM5_SLAVE_MODE	0x10
#define  COM5_SYSTEMCLOCK48MHZ	0x80
#define REG_COM6		0x0f	/* HREF & ADBLC options */
#define REG_AEC			0x10	/* More bits of AEC value */
#define REG_CLKRC		0x11	/* Clocl control */
#define  CLK_EXT		0x40	/* Use external clock directly */
#define  CLK_SCALE		0x3f	/* Mask for internal clock scale */
#define REG_COM7		0x12	/* SCCB reset, output format */
#define  COM7_RESET		0x80
#define  COM7_FMT_MASK		0x38
#define  COM7_FMT_VGA		0x40
#define	 COM7_FMT_CIF		0x20
#define  COM7_FMT_QVGA		0x10
#define  COM7_FMT_QCIF		0x08
#define	 COM7_RGB		0x04
#define	 COM7_YUV		0x00
#define	 COM7_BAYER		0x01
#define	 COM7_PBAYER		0x05
#define REG_COM8		0x13	/* AGC/AEC options */
#define  COM8_FASTAEC		0x80	/* Enable fast AGC/AEC */
#define  COM8_AECSTEP		0x40	/* Unlimited AEC step size */
#define  COM8_BFILT		0x20	/* Band filter enable */
#define  COM8_AGC		0x04	/* Auto gain enable */
#define  COM8_AWB		0x02	/* White balance enable */
#define  COM8_AEC		0x01	/* Auto exposure enable */
#define REG_COM9		0x14	/* Control 9  - gain ceiling */
#define REG_COM10		0x15	/* Slave mode, HREF vs HSYNC, signals negate */
#define  COM10_HSYNC		0x40	/* HSYNC instead of HREF */
#define  COM10_PCLK_HB		0x20	/* Suppress PCLK on horiz blank */
#define  COM10_HREF_REV		0x08	/* Reverse HREF */
#define  COM10_VS_LEAD		0x04	/* VSYNC on clock leading edge */
#define  COM10_VS_NEG		0x02	/* VSYNC negative */
#define  COM10_HS_NEG		0x01	/* HSYNC negative */
#define REG_HSTART		0x17	/* Horiz start high bits */
#define REG_HSTOP		0x18	/* Horiz stop high bits */
#define REG_VSTART		0x19	/* Vert start high bits */
#define REG_VSTOP		0x1a	/* Vert stop high bits */
#define REG_PSHFT		0x1b	/* Pixel delay after HREF */
#define REG_MIDH		0x1c	/* Manuf. ID high */
#define REG_MIDL		0x1d	/* Manuf. ID low */
#define REG_MVFP		0x1e	/* Mirror / vflip */
#define  MVFP_MIRROR		0x20	/* Mirror image */
#define  MVFP_FLIP		0x10	/* Vertical flip */
#define REG_BOS			0x20	/* B channel Offset  */
#define REG_GBOS		0x21	/* Gb channel Offset  */
#define REG_GROS		0x22	/* Gr channel Offset  */
#define REG_ROS			0x23	/* R channel Offset  */
#define REG_AEW			0x24	/* AGC upper limit */
#define REG_AEB			0x25	/* AGC lower limit */
#define REG_VPT			0x26	/* AGC/AEC fast mode op region */
#define REG_BBIAS		0x27	/* B channel output bias */
#define REG_GBBIAS		0x28	/* Gb channel output bias */
#define REG_GRCOM		0x29	/* Analog BLC & regulator */
#define REG_EXHCH		0x2a	/* Dummy pixel insert MSB */
#define REG_EXHCL		0x2b	/* Dummy pixel insert LSB */
#define REG_RBIAS		0x2c	/* R channel output bias */
#define REG_ADVFL		0x2d	/* LSB of dummy pixel insert */
#define REG_ADVFH		0x2e	/* MSB of dummy pixel insert */
#define REG_YAVE		0x2f	/* Y/G channel average value */
#define REG_HSYST		0x30	/* HSYNC rising edge delay LSB*/
#define REG_HSYEN		0x31	/* HSYNC falling edge delay LSB*/
#define REG_HREF		0x32	/* HREF pieces */
#define REG_CHLF		0x33	/* reserved */
#define REG_ADC			0x37	/* reserved */
#define REG_ACOM		0x38	/* reserved */
#define REG_OFCON		0x39	/* Power down register */
#define  OFCON_PWRDN		0x08	/* Power down bit */
#define REG_TSLB		0x3a	/* YUVU format */
#define  TSLB_YUYV_MASK		0x0c	/* UYVY or VYUY - see com13 */
#define REG_COM11		0x3b	/* Night mode, banding filter enable */
#define  COM11_NIGHT		0x80	/* NIght mode enable */
#define  COM11_NMFR		0x60	/* Two bit NM frame rate */
#define  COM11_BANDING		0x01	/* banding filter */
#define REG_COM12		0x3c	/* HREF option, UV average */
#define  COM12_HREF		0x80	/* HREF always */
#define REG_COM13		0x3d	/* Gamma selection, Color matrix enable, UV delay*/
#define  COM13_GAMMA		0x80	/* Gamma enable */
#define	 COM13_UVSAT		0x40	/* UV saturation auto adjustment */
#define  COM13_UVSWAP		0x01	/* V before U - w/TSLB */
#define REG_COM14		0x3e	/* Edge enhancement options */
#define REG_EDGE		0x3f	/* Edge enhancement factor */
#define REG_COM15		0x40	/* Output range, RGB 555 vs 565 option */
#define  COM15_R10F0		0x00	/* Data range 10 to F0 */
#define	 COM15_R01FE		0x80	/* 01 to FE */
#define  COM15_R00FF		0xc0	/* 00 to FF */
#define  COM15_RGB565		0x10	/* RGB565 output */
#define  COM15_RGB555		0x30	/* RGB555 output */
#define  COM15_SWAPRB		0x04	/* Swap R&B */
#define REG_COM16		0x41	/* Color matrix coeff double option */
#define  COM16_AWBGAIN		0x08	/* AWB gain enable */
#define REG_COM17		0x42	/* Single Frame out, Banding filter */
/* n = 1...9, 0x4f..0x57 */
#define	REG_MTX(__n)		(0x4f + (__n) - 1)
#define REG_MTXS		0x58
/* Lens Correction Option 1...5, __n = 0...5 */
#define REG_LCC(__n)		(0x62 + (__n) - 1)
#define  LCC5_LCC_ENABLE	0x01	/* LCC5, enable lens correction */
#define  LCC5_LCC_COLOR		0x04
#define REG_MANU		0x67	/* Manual U value */
#define REG_MANV		0x68	/* Manual V value */
#define REG_HV			0x69	/* Manual banding filter MSB */
#define REG_MBD			0x6a	/* Manual banding filter value */
#define REG_GSP			0x6c	/* Gamma curve */
#define  GSP_LEN		15
#define REG_GST			0x7c	/* Gamma curve */
#define  GST_LEN		15
#define REG_COM22		0x8c	/* Edge enhancement, denoising */
#define  COM22_WHTPCOR		0x02	/* White pixel correction enable */
#define  COM22_WHTPCOROPT	0x01	/* White pixel correction option */
#define  COM22_DENOISE		0x10	/* White pixel correction option */
#define REG_COM23		0x8d	/* Color bar test,color gain */
#define REG_DBLC1		0x8f	/* Digital BLC */
#define REG_DBLC_B		0x90	/* Digital BLC B chan offset */
#define REG_DBLC_R		0x91	/* Digital BLC R chan offset */
#define REG_DM_LNL		0x92	/* Dummy line low 8 bits */
#define REG_DM_LNH		0x93	/* Dummy line high 8 bits */
#define REG_LCCFB		0x9d	/* Lens Correction B chan */
#define REG_LCCFR		0x9e	/* Lens Correction R chan */
#define REG_DBLC_GB		0x9f	/* Digital BLC GB chan offset */
#define REG_DBLC_GR		0xa0	/* Digital BLC GR chan offset */
#define REG_AECHM		0xa1	/* Exposure Value - AEC MSB 6 bits */
#define REG_BD50ST		0xa2	/* Banding Filter Value 50Hz */
#define REG_BD60ST		0xa3	/* Banding Filter Value 60Hz */

#define OV965X_PID_MSB		0x96
#define OV9650_PID_LSB		0x50
#define OV9652_PID_LSB		0x52




static inline int gt2440_ov9650_write_reg(struct i2c_client *client, u8 addr, u8 val)
{
	u8 buf[2] = { addr, val };
	int rets = i2c_master_send(client, buf, 2);
	return rets == 2 ? 0 : rets;
}
static inline int gt2440_ov9650_read_reg(struct i2c_client *client, u8 addr, u8 *val)
{
	u8 buf = addr;
	struct i2c_msg msg = {
		.addr = client->addr,
		.flags = 0,
		.len = 1,
		.buf = &buf
	};
	int rets;
	rets = i2c_transfer(client->adapter, &msg, 1);
	if (rets == 1) {
		msg.flags = I2C_M_RD;
		rets = i2c_transfer(client->adapter, &msg, 1);

		if (rets == 1)
			*val = buf;
	}
	return rets == 1 ? 0 : rets;
}


/***** declare function *****/
static void __gt2440_ov9650_set_power(struct gt2440_ov9650_info *info, int on);
static int gt2440_ov9650_write_array(struct i2c_client *client,
			      const struct gt2440_ov9650_reg *regs,
			      unsigned int len);
static int gt2440_ov9650_set_gamma_curve(struct gt2440_ov9650_info *info);
static int gt2440_ov9650_set_color_matrix(struct gt2440_ov9650_info *info);
static int __gt2440_ov9650_set_params(struct gt2440_ov9650_info *info);
static int gt2440_ov9650_set_framesize(struct v4l2_mbus_framefmt *framefmt,
				   const struct gt2440_ov9650_framesize **framesizes);


static void gt2440_ov9650_set_format(struct gt2440_ov9650_info *info,
			      struct v4l2_mbus_framefmt *framefmt);
static int gt2440_ov9650_s_power(struct v4l2_subdev *subdev, int on);
static int gt2440_ov9650_log_status(struct v4l2_subdev *subdev);
static int gt2440_ov9650_s_stream(struct v4l2_subdev *subdev, int on);
static int gt2440_ov9650_enum_mbus_code(struct v4l2_subdev *subdev,
				 struct v4l2_subdev_fh *fh,
				 struct v4l2_subdev_mbus_code_enum *code_enum);
static int gt2440_ov9650_enum_frame_size(struct v4l2_subdev *subdev,
				   struct v4l2_subdev_fh *fh,
				   struct v4l2_subdev_frame_size_enum *frame_size_enum);
static int gt2440_ov9650_get_fmt(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
			  struct v4l2_subdev_format *format);
static int gt2440_ov9650_set_fmt(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
			  struct v4l2_subdev_format *format );


static int gt2440_ov9650_registered(struct v4l2_subdev *subdev);
static int gt2440_ov9650_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *subdev_fh);
static int gt2440_ov9650_s_ctrl(struct v4l2_ctrl *ctrl);





/***** debug  *****/
#define GT2440_ov9650_DEBUG
#ifdef GT2440_ov9650_DEBUG
#define dprintk printk
#else
#define dprintk(...)
#endif


#endif


